//
// Created by edward on 22-11-22.
//

#ifndef CONCURRENCE_SINGLETON_H
#define CONCURRENCE_SINGLETON_H

#include <mutex>
#include <memory>

namespace edward {

    template<typename T>
    class SingleTon {
        using Ptr = std::shared_ptr<T>;
        static Ptr p;
        static std::once_flag flag;
        template<typename ...Args>
        static void init(Args&&...args) {
            p.reset(new T(std::forward<Args>(args)...));
        }

    public:
        template<typename ...Args>
        static Ptr getInstance(Args&& ...args) {
            /*
            //也可以使用lambda表达式实现上面成员函数的功能，但是不是很必要，使用成员函数更加直观而且避免了每次调用都创建lambda表达式和传递p的性能消耗
            auto init = [](Ptr &p, auto&& ...args1) {
                p.reset(new T(std::forward<decltype(args1)>(args1)...));
            };
            */
            //如果不使用lambda表达式而是使用静态成员函数进行初始化，则必须在传入给call_once的时候就进行实例化
            //否则编译器会提示init是一个未解决的重载函数
            std::call_once(flag, init<Args...>, std::forward<Args>(args)...);
            //static Ptr p = std::make_shared<T>(std::forward<Args>(args)...);
            return p;
        }
    };

    template<typename T>
    std::shared_ptr<T> SingleTon<T>::p;

    template<typename T>
    std::once_flag SingleTon<T>::flag;

}

#endif //CONCURRENCE_SINGLETON_H
